package com.hellobike.haxing.web.shop;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CannedAccessControlList;
import com.google.common.collect.Maps;
import com.hellobike.haxing.common.ResponseCodeEnum;
import com.hellobike.haxing.config.OssConfig;
import com.hellobike.haxing.convert.ProductInfoConvert;
import com.hellobike.haxing.order.api.IOrderRewardApi;
import com.hellobike.haxing.order.model.vo.OrderRewardVo;
import com.hellobike.haxing.order.result.Page;
import com.hellobike.haxing.order.result.PageResult;
import com.hellobike.haxing.order.result.Result;
import com.hellobike.haxing.order.result.ResultCode;
import com.hellobike.haxing.product.api.IProductService;
import com.hellobike.haxing.product.model.vo.ProductVo;
import com.hellobike.haxing.request.order.CommissProductPageRequest;
import com.hellobike.haxing.request.search.SearchRequest;
import com.hellobike.haxing.request.shop.*;
import com.hellobike.haxing.response.shop.ProductListVo;
import com.hellobike.haxing.response.shop.ShopProductPosterVo;
import com.hellobike.haxing.search.api.ProductSearchApi;
import com.hellobike.haxing.search.api.ShopSearchApi;
import com.hellobike.haxing.search.vo.SearchProductParam;
import com.hellobike.haxing.search.vo.SearchProductVo;
import com.hellobike.haxing.user.api.*;
import com.hellobike.haxing.user.request.ShopAccountRequest;
import com.hellobike.haxing.user.request.ShopLeatUserCountRequest;
import com.hellobike.haxing.user.response.*;
import com.hellobike.haxing.user.vo.*;
import com.hellobike.haxing.util.CustomWKHtmlToPdfUtil;
import com.hellobike.haxing.util.RedisUtil;
import com.hellobike.haxing.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RequestMapping("/shop")
@RestController
@Data
@Api(tags = "店铺接口")
@Slf4j
public class ShopController {

    private static TemplateEngine templateEngine = null;

    static {
        templateEngine = new TemplateEngine();
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        resolver.setPrefix("/templates/");
        resolver.setSuffix(".html");
        templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(resolver);
    }

    @Reference
    private ShopSearchApi shopSearchApi;

    @Reference(version = "1.0.0")
    private ShopApi shopApi;

    @Reference(version = "1.0.0")
    private ShopAccountApi shopAccountApi;
    @Autowired
    private UserUtil userUtil;
    @Reference(version = "1.0.0")
    private ShopStaticsApi shopStaticsApi;
    @Reference(version = "1.0.0")
    private ShopProductStaticsApi shopProductStaticsApi;
    @Reference(version = "1.0.0")
    private IProductService productService;
    @Reference(version = "1.0.0")
    private ShareApi shareApi;
    @Reference(version = "1.0.0", check = true)
    private ProductSearchApi productSearchApi;

    private UserApi userApi;

    @Autowired
    private RedisUtil redisUtil;


    @Reference(version = "1.0.0")
    private IOrderRewardApi orderRewardApi;


    @PostMapping(value = "/info")
    @ApiOperation("查询门店信息")
    public Result<ShopVo> info() {
        Result<ShopVo> result = new Result<>();
        UserVo userVo = userUtil.getUser();
        ShopVo shopVo = shopApi.queryShopInfo(userVo.getShopVo().getId());
        result.success("").setData(shopVo);
        return result;
    }

    /**
     * 分享参数第一位是商品id，第二位是拼团ID,第三位是用户ID,第四位是分享所在的店铺ID
     */
    private static String shareParamTemplate = "%d,%d,%d,%d";

    @RequestMapping(value = "/apply", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation("团长申请")
    public Result<ShopApplyResponse> apply(@ApiParam("团长申请") @RequestBody com.hellobike.haxing.user.vo.ShopVo shopVo) {
        log.info("===门店录入请求参数=={}==", JSON.toJSONString(shopVo));
        shopVo.setLeadShopId(userUtil.getUser().getShopVo().getId());
        shopVo.setRecommender(userUtil.getUser().getShopVo().getRealName());
        ShopApplyResponse shopApplyResponse = shopApi.apply(shopVo);
        Result<ShopApplyResponse> result = new Result<>();
        result.setData(shopApplyResponse);
        return result;
    }

    @PostMapping(value = "/updateBusinessTime")
    @ApiOperation("更新营业时间")
    public Result<String> updateBusinessTime(@ApiParam(name = "businessTime营业时间", required = true) @RequestBody UpdateTimeRequest request) {
        BaseResponse<String> baseResponse = shopApi.updateBusinessTime(request.getBusinessTime(), userUtil.getUser().getShopVo().getId());
        return Result.ok();
    }

    @PostMapping(value = "/queryShopAccountPage")
    @ApiOperation("分页查询账单信息dddd")
    public PageResult<ShopAccountVo> queryShopAccountPage(@RequestBody AccountPageRequest res) {
        ShopAccountRequest request = new ShopAccountRequest();
        request.setShopId(userUtil.getUser().getShopVo().getId());
        request.setType(res.getType());
        PageRespones<ShopAccountVo> baseResponse = shopAccountApi.queryPage(res.getCurPage(), res.getPageSize(), request);
        PageResult<ShopAccountVo> pageResult = new PageResult<>();
        pageResult.success("").setData(baseResponse.getData());
        pageResult.setPage(new Page());
        pageResult.getPage().setTotal(baseResponse.getTotal());
        pageResult.getPage().setPages(baseResponse.getPages());
        return pageResult;
    }

    @PostMapping(value = "/queryRejectLeadShopPage")
    @ApiOperation("驳回分页查询")
    public PageResult<ShopVo> queryRejectLeadShopPage(@RequestBody ShopRejectLeadPageRequest res) {
        PageRespones<ShopVo> baseResponse = shopApi.queryRejectLeadShopPage(res.getCurPage(), res.getPageSize(), userUtil.getUser().getShopVo().getId());
        PageResult<ShopVo> shopVoPageResult = new PageResult<>();
        shopVoPageResult.success("").setData(baseResponse.getData());
        shopVoPageResult.setPage(new Page());
        shopVoPageResult.getPage().setTotal(baseResponse.getTotal());
        shopVoPageResult.getPage().setPages(baseResponse.getPages());
        return shopVoPageResult;
    }

    @GetMapping(value = "/queryShopInfo")
    @ApiOperation("查询提货点详情")
    public Result<ShopVo> queryShopInfo(@ApiParam(name = "shopId", required = true) @Valid @NotNull @RequestParam Long shopId) {
        ShopVo shopVo = shopApi.queryShopInfo(shopId);
        return Result.ok(shopVo);
    }

    @DeleteMapping(value = "/deleteShop")
    @ApiOperation("删除驳回门店")
    public Result<ShopVo> deleteShop(@ApiParam(required = true) @RequestBody ShopDeleteRequest res) {
        int t = shopApi.deleteLeadShop(res.getShopId(), userUtil.getUser().getShopVo().getId());
        if (t == 0) {
            return Result.error(ResultCode.FAIL, "删除失败，只有驳回门店才允许删除");
        }
        return Result.ok(null, "删除成功");
    }

    /**
     * 发展门店统计（发展的门店审核通过和审核拒绝统计）
     */
    @GetMapping(value = "/queryShopLeadAuditCount")
    @ApiOperation("审核通过和审核拒绝统计")
    public Result<ShopLeadResponse> queryShopLeadAuditCount() {
        ShopLeadResponse shopLeadResponse = shopApi.queryLeadAuditCount(userUtil.getUser().getShopVo().getId());
        return Result.ok(shopLeadResponse);
    }

    /**
     * 销量比拼
     */
    @GetMapping(value = "/getShopStaticSaleCount")
    @ApiOperation("销量比拼,type类型1天2月3累计")
    public Result<ShopProdStaticSalesResponse> getShopStaticSaleCount(@Valid @NotNull @ApiParam(required = true, name = "type") @RequestParam Integer type) {
        ShopProdStaticSalesResponse shopStaticSalesResponse = shopProductStaticsApi.getShopProdStaticSaleCount(userUtil.getUser().getShopVo().getId(), type);
        return Result.ok(shopStaticSalesResponse);
    }

    /**
     * 快捷报单
     */
    @GetMapping(value = "/getShopProdStaticCount")
    @ApiOperation("快捷报单统计")
    public Result<ShopProdStaticResponse> getShopProdStaticCount() {
        ShopProdStaticResponse shopProdStaticResponse = shopProductStaticsApi.getShopProdStaticCount(userUtil.getUser().getShopVo().getId());
        return Result.ok(shopProdStaticResponse);
    }

    /**
     * 订单商品图文提取
     */
    @RequestMapping(value = "/queryShopProdWeekPage", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation("订单商品图文提取")
    public PageResult<ShopProductStaticsVo> queryShopProdWeekPage(@RequestBody CommissProductPageRequest res) {
        PageRespones<ShopProductStaticsVo> baseResponse = shopProductStaticsApi.queryShopProdWeekCommissCountPage(res.getCurPage(), res.getPageSize(), userUtil.getUser().getShopVo().getId(), res.getType());
        PageResult<ShopProductStaticsVo> shopVoPageResult = new PageResult<>();
        shopVoPageResult.success("").setData(baseResponse.getData());
        shopVoPageResult.setPage(new Page());
        shopVoPageResult.getPage().setTotal(baseResponse.getTotal());
        shopVoPageResult.getPage().setPages(baseResponse.getPages());
        log.info("shopvopageresult:{}", JSON.toJSONString(shopVoPageResult));
        return shopVoPageResult;
    }

    /**
     * 商品图文提取及搜索
     */
    @RequestMapping(value = "/shopProductSearch", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation("商品图文提取及搜索")
    public PageResult<ProductListVo> search(@RequestBody SearchRequest request) {
        log.info("search-request:{}", JSON.toJSONString(request));
        SmallShopVo shopVo = userUtil.getUser().getShopVo();
        PageResult<ProductListVo> result = new PageResult<>();
        SearchProductParam searchProductParam = new SearchProductParam();
        searchProductParam.setPageSize(request.getPageSize());
        searchProductParam.setCurrPage(request.getCurPage());
        searchProductParam.setKeyword(request.getKeyword());
        searchProductParam.setShopId(shopVo.getId());
        searchProductParam.setCityId(shopVo.getCityId());
        searchProductParam.setOrderType(request.getOrderType());
        com.hellobike.haxing.search.response.PageRespones<SearchProductVo> respones = productSearchApi.searchProduct(searchProductParam);
        Page page = new Page();
        page.setPages(respones.getPages());
        page.setTotal(respones.getTotal());
        if (!CollectionUtils.isEmpty(respones.getData())) {
            result.setData(new ArrayList<>());
            List<ProductListVo> lists = respones.getData().stream().map(searchProductVo -> {
                ProductListVo productListVo = new ProductListVo();
                ProductInfoConvert.convert(searchProductVo, productListVo);
                return productListVo;
            }).collect(Collectors.toList());
            result.setData(lists);
        }
        result.setPage(page);
        return result;
    }


    /**
     * TODO 店铺ID不加参数
     *
     * @param request
     * @return
     */
    @PostMapping(value = "/generate")
    @ApiOperation("生成分享海报")
    public Result<String> generate(@RequestBody ShareRequest request) {
        UserVo userVo = userUtil.getUser();
        Result<String> result = new Result<>();
        Map<String, Object> dataMap = Maps.newHashMap();
        dataMap.put("subjectAndContentList", "subjectAndContentList");
        if (request.getType() == 3) {
            OrderRewardVo orderRewardVo = orderRewardApi.getOrderReward(userVo.getShopVo().getId());
            if (orderRewardVo != null) {
                dataMap.put("pressImg", "https://hxn-product-image.oss-cn-beijing.aliyuncs.com/test/icon/471605149832_.pic_hd.jpg");
                dataMap.put("shareImg", orderRewardVo.getPlaybill());
            }
        } else {
            PlaybillImgVo playbillImgVo = shareApi.queryPlaybillInfo();
            log.info("playbillImg:{}", JSON.toJSONString(playbillImgVo));
            if (playbillImgVo != null) {
                if (request.getType() == 1) {
                    dataMap.put("shareImg", playbillImgVo.getCampaignPlaybillUrl());
                    dataMap.put("pressImg", "https://hxn-product-image.oss-cn-beijing.aliyuncs.com/test/icon/681606205200_.pic_hd.jpg");
                } else {
                    dataMap.put("pressImg", "https://hxn-product-image.oss-cn-beijing.aliyuncs.com/test/icon/471605149832_.pic_hd.jpg");
                    dataMap.put("shareImg", playbillImgVo.getShopPlaybillUrl());
                }
            }
        }

        String key = "redis:share:img:shop:" + userVo.getShopVo().getId() + ":" + request.getType() + ":" + request.getPath() + ":" + request.getPlatform();
        String sharePath = redisUtil.getObject(String.class, key);
        if (StringUtils.isEmpty(sharePath)) {
            ShareCodeResponse response = shareApi.generateShareCode(request.getPath(), userVo.getShopVo().getId() + "");
            if (response.isSuccess()) {
                dataMap.put("img", response.getData());
            }
            Context ctx = new Context();
            ctx.setVariables(dataMap);
            try {
                String fileName = "/tmp/" + RandomStringUtils.randomNumeric(8) + ".html";
                String jpgName = "/tmp/" + RandomStringUtils.randomNumeric(8) + ".png";
                templateEngine.process("share", ctx, new FileWriter(fileName));
                String command = CustomWKHtmlToPdfUtil.getCommand(fileName, jpgName);
                if (StringUtils.isNotEmpty(command)) {
                    Process process = Runtime.getRuntime().exec(command);
                    process.waitFor();
                }
                FileInputStream fis = new FileInputStream(jpgName);
                String compressFilePath = "/tmp/" + RandomStringUtils.randomNumeric(8) + ".png";
                Thumbnails.of(fis).size(361, 585).toFile(new File(compressFilePath));
                String ossFileName = System.currentTimeMillis() + "-" + UUID.randomUUID().toString().substring(0, 18) + ".png";
                ossClient.putObject(ossConfig.getBucketName(), ossFileName, new FileInputStream(new File(compressFilePath)));
                ossClient.setObjectAcl(ossConfig.getBucketName(), ossFileName, CannedAccessControlList.PublicRead);
                String prefix = ossConfig.getDomain();
                if (!prefix.endsWith("/")) {
                    prefix = prefix + "/";
                }
                String fileUrl = prefix + ossFileName;
                redisUtil.setObject(key, fileUrl, 10, TimeUnit.MINUTES);
                result.success("").setData(fileUrl);
                return result;
            } catch (Exception ex) {
                log.error("", ex);
                result.faild(500, ex.getMessage());
                return result;
            }
        }
        result.success("").setData(sharePath);
        return result;

    }

    @Autowired
    private OSSClient ossClient;
    @Autowired
    private OssConfig ossConfig;

    /**
     * 门店会员数统计
     */
    @GetMapping(value = "/getLeadApproveCount")
    @ApiOperation("门店会员数统计")
    public Result<ShopLeadApproveResponse> getLeadApproveCount() {
        SmallShopVo shop = userUtil.getUser().getShopVo();
        ShopLeadApproveResponse vo = shopApi.getLeadApproveCount(shop.getId());
        vo.setAddress(shop.getAddress());
        return Result.ok(vo);
    }

    @PostMapping(value = "/queryLeadShopOrderPage")
    @ApiOperation("门店会员订单分页查询")
    public PageResult<ShopLeadOrderCountVo> queryLeadShopOrderPage(@RequestBody ShopLeadUserOrderPageRequest res) {
        ShopLeatUserCountRequest rest = new ShopLeatUserCountRequest();
        rest.setSerach(res.getSerach());
        /**
         * 增加日志
         */
        rest.setShopId(userUtil.getUser().getShopVo().getId());
        PageRespones<ShopLeadOrderCountVo> baseResponse = shopStaticsApi.getShopVipUserCount(res.getCurPage(), res.getPageSize(), rest);
        PageResult<ShopLeadOrderCountVo> shopVoPageResult = new PageResult<>();
        shopVoPageResult.success("").setData(baseResponse.getData());
        shopVoPageResult.setPage(new Page());
        shopVoPageResult.getPage().setTotal(baseResponse.getTotal());
        shopVoPageResult.getPage().setPages(baseResponse.getPages());
        return shopVoPageResult;
    }

    @GetMapping(value = "/getShopProductPoster")
    @ApiOperation("生成门店商品海报")
    public Result<ShopProductPosterVo> getShopProductPoster(@Valid @NotNull @ApiParam(required = true, name = "productId") @RequestParam Long productId) {
        SmallShopVo shop = userUtil.getUser().getShopVo();
        ProductVo productVo = productService.getProductDetail(productId);
        ShopProductPosterVo vo = new ShopProductPosterVo();
        vo.setAddress(shop.getAddress());
        vo.setShopName(shop.getShopName());
        vo.setTitle(productVo.getTitle());
        vo.setMainImage(productVo.getMainImage());
        List<BigDecimal> lists = productVo.getSkuList().stream().map(skuVo -> skuVo.getPrice()).collect(Collectors.toList());
        lists.sort(Comparator.comparing(BigDecimal::doubleValue));
        vo.setPrice(lists.get(0));
        String param = String.format(shareParamTemplate, productId, null, null, shop.getId()).replaceAll(
                "null", "");
        //pages/goodsDetails/goodsDetails
        //临时把page参数去掉
        ShareCodeResponse response = shareApi.generateShareCode("", param);
        if (response.isSuccess()) {
            vo.setCodeUrl(response.getData());
        } else {
            return Result.error(ResponseCodeEnum.SYSTEM_ERROR.code(), "二维码生成失败");
        }
        return Result.ok(vo);
    }

}
